package com.util.excelUtil;


import com.util.excelUtil.annotation.ExcelTitle;
import lombok.Data;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @Description:  非线程安全
 * @Author: yangzhiwei
 * @Date: 2021/1/21 14:12
 */
@Data
public class ExportExcelUtil<T> {

    private Map<String,String> specifiedTitleMap;

    private boolean isSpecified = false;

    //private ConcurrentHashMap specifiedTitleMap;



    /**
     * XSSFWorkbook类的注释如下：
     * High level representation of a SpreadsheetML workbook.  This is the first object most users
     * will construct whether they are reading or writing a workbook.  It is also the
     * top level object for creating new sheets/etc.
     */
    public XSSFWorkbook exportWorkBook(List<T> list) throws NoSuchFieldException, IllegalAccessException {
        if (list == null || list.size() == 0) {
            return new XSSFWorkbook();
        }

        List<MetaDataRecord> metaDataRecords =  parseEntityGetTitleAndMapFiled(list.get(0));
        //创建book
        XSSFWorkbook book = new XSSFWorkbook();
        //创建sheet
        XSSFSheet sheet = createSheet(book);
        //创建标题列
        creatTitle(sheet,metaDataRecords);
        //添加数据
        addData(sheet,metaDataRecords,list);

        return book;
    }

    private void addData(XSSFSheet sheet, List<MetaDataRecord> metaDataRecords,List<T> list) throws NoSuchFieldException, IllegalAccessException {
        int dataRow = 1;
        for(T t : list) {
            XSSFRow rowForData = sheet.createRow(dataRow++);
            for(int i = 0; i < metaDataRecords.size(); i++) {
                XSSFCell cell = rowForData.createCell(i);
                //从t中取 与当前 metaDataRecord对应的字段 : 虽然时间复杂度为n方，但是对象字段都不是很多，没必要用 map
                String fieldName = metaDataRecords.get(i).getFieldName();
                String value = getFieldValue(fieldName,t);
                cell.setCellValue(value);
            }
        }
    }

    //创建 Excel标题行
    private void creatTitle(XSSFSheet sheet,List<MetaDataRecord> metaDataRecords) {
        XSSFRow title = sheet.createRow(0);
        for(int i = 0; i < metaDataRecords.size(); i++) {
            XSSFCell cell = title.createCell(i);
            cell.setCellValue(metaDataRecords.get(i).getTitle());
        }
    }

    // 创建Sheet
    private XSSFSheet createSheet(XSSFWorkbook book) {
        XSSFSheet sheet = book.createSheet("sheet1");
        return sheet;
    }

    /**
     * 保证Field域为基础类型(或其封装类型)
     * @param
     * @param t
     * @return
     */
    private String getFieldValue(String fieldName, T t) throws IllegalAccessException, NoSuchFieldException {
        Class clzz = t.getClass();
        Field[] fields = clzz.getDeclaredFields();
        System.out.println("==================FieldName");
        for (Field field : fields){
            System.out.println(field.getName());
        }
        Field field = clzz.getDeclaredField(fieldName);
        System.out.println(field.getName());
        field.setAccessible(true);
        // field.get
        Object obj = field.get(t);
        if (obj == null) {
            return "";
        }
        return field.get(t) + "";
    }



    /**
     * 获取用于生成 Excel 的 Field的相关信息
     * @param entity
     * @return
     */
    private List<MetaDataRecord> parseEntityGetTitleAndMapFiled(T entity) {
        List<MetaDataRecord> resList = new ArrayList();
        Class clzz = entity.getClass();
        //获取所有的列
        Field[] fields = clzz.getDeclaredFields();
        ExcelTitle annotation;
        for(Field field : fields) {
            if (field.isAnnotationPresent(ExcelTitle.class)) {
                annotation = field.getAnnotation(ExcelTitle.class);
                MetaDataRecord meta = new MetaDataRecord();
                if (isSpecified && specifiedTitleMap.containsKey(field.getName())) {//开启指定,且包含
                    meta.setTitle(specifiedTitleMap.get(field.getName()));
                } else {
                    meta.setTitle(annotation.value());
                }

                meta.setPriority(annotation.priority());
                meta.setFieldName(field.getName());

                resList.add(meta);
            }
        }

        resList.sort(new Comparator<MetaDataRecord>() {
            @Override
            public int compare(MetaDataRecord o1, MetaDataRecord o2) {
                return o1.priority - o2.priority;
            }
        });

        return resList;
    }

    /**
     * 为特定Field手动指定标题。 某一Field需要多个标题时使用
     * @param fieldName
     * @param sepcifiedTitle
     */
    public void addSpecifiedTitle(String fieldName,String sepcifiedTitle){
        if(specifiedTitleMap == null) {
            isSpecified = true;
            specifiedTitleMap = new HashMap();
        }
        specifiedTitleMap.put(fieldName,sepcifiedTitle);
    }

    @Data
    public static class MetaDataRecord{
        private String fieldName;
        private int priority;
        private String title;
    }

    /**
     *  response.setContentType("application/binary;charset=UTF-8");
     *         OutputStream out = response.getOutputStream();
     *         response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode("用户表.xlsx", "utf-8"));
     *         response.setContentType("application/vnd.ms-excel;charset=UTF-8");
     *         response.setHeader("Pragma", "no-cache");
     *         response.setHeader("Cache-Control", "no-cache");
     *         response.setDateHeader("Expires", 0);
     */

}
